﻿using DevExpress.Utils.Win;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Popup;
using Microsoft.VisualBasic.CompilerServices;
using Rimifier.Properties;
using Rimifier.Support;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Xml;

namespace Rimifier
{
	public partial class MainApplication : BaseForm
	{
		public MainApplication()
		{
			InitializeComponent();
		}

		#region Private methods

		private Boolean CheckFileExistance()
		{
			if (!File.Exists(Settings.Default.SelectedSaveFilePath))
			{
				// We are NOT good to load
				XtraMessageBox.Show("There is no save file selected to load.", UtilityFunctions.AssemblyTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);

				return false;
			}

			return true;
		}

		private void SaveFile(ref XmlDocument xdoc, String saveInfo)
		{
			if (!Directory.Exists(Settings.Default.BackupSaveFilePath))
			{
				Directory.CreateDirectory(Settings.Default.BackupSaveFilePath);
			}

			xdoc.Save(Settings.Default.BackupSaveFilePath + Path.GetFileName(saveInfo));
		}

		private void ReloadResource(ResourceTypesOld resourceTypeOld)
		{
			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			XmlNode selectSingleNode;

			Boolean selectResult;
			Int32 selectedValue;

			switch (resourceTypeOld)
			{
				case ResourceTypesOld.Money:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Money");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinMoney.Value = selectedValue;
						}
					}
					break;

				case ResourceTypesOld.Food:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Food");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinFood.Value = selectedValue;
						}
					}
					break;

				case ResourceTypesOld.Metal:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Metal");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinMetal.Value = selectedValue;
						}
					}
					break;

				case ResourceTypesOld.Medicine:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Medicine");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinMedicine.Value = selectedValue;
						}
					}
					break;

				case ResourceTypesOld.Shells:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Shells");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinShells.Value = selectedValue;
						}
					}
					break;

				case ResourceTypesOld.Missiles:
					selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Missiles");
					if (selectSingleNode != null)
					{
						selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

						if (selectResult)
						{
							SpinMissiles.Value = selectedValue;
						}
					}
					break;
			}
		}

		private void LoadResources()
		{
			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);

			Boolean selectResult;
			Int32 selectedValue;

			#region Money

			var selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Money");

			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinMoney.Value = selectedValue;
				}
			}

			#endregion

			#region Food

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Food");
			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinFood.Value = selectedValue;
				}
			}

			#endregion

			#region Metal

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Metal");
			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinMetal.Value = selectedValue;
				}
			}

			#endregion

			#region Medicine

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Medicine");
			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinMedicine.Value = selectedValue;
				}
			}

			#endregion

			#region Shells

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Shells");
			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinShells.Value = selectedValue;
				}
			}

			#endregion

			#region Missiles

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Missiles");
			if (selectSingleNode != null)
			{
				selectResult = Int32.TryParse(selectSingleNode.InnerText, out selectedValue);

				if (selectResult)
				{
					SpinMissiles.Value = selectedValue;
				}
			}

			#endregion
		}

		private void LoadColonists(String colonistId = "")
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			var savefile = Settings.Default.SelectedSaveFilePath;

			ListColonist.DataSource = null;
			ListColonist.Items.Clear();

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			IEnumerator enumerator = null;

			var xmlNodeLists = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");

			var fetchedCollection = new PawnList();

			try
			{
				if (xmlNodeLists != null)
				{
					enumerator = xmlNodeLists.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlElement)enumerator.Current;
						if (current.InnerXml.Contains("<Team>Colonist</Team>"))
						{
							var elementByTagId = current.GetElementsByTagName("ID");
							var elementByTagName = current.GetElementsByTagName("CharacterName");

							var tempPawnItem = new PawnListItem
							{
								ColonistId = elementByTagId[0].InnerText,
								ColonistName = elementByTagName[0].InnerText,
								DisplayName = String.Format("{0} ({1})", elementByTagName[0].InnerText, elementByTagId[0].InnerText)
							};

							fetchedCollection.Add(tempPawnItem);
						}
					}

					ListColonist.DataSource = fetchedCollection;
					ListColonist.ValueMember = "ColonistId";
					ListColonist.DisplayMember = "DisplayName";
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}
		}

		private void UpdateColonist()
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			#region Validation

			var selectedPawn = ListColonist.SelectedItem as PawnListItem;

			if (selectedPawn == null)
			{
				XtraMessageBox.Show("Saving failed! No colonist selected.", UtilityFunctions.AssemblyTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return;
			}

			if (String.IsNullOrEmpty(TextColonistName.Text))
			{
				XtraMessageBox.Show("Saving failed! Please name the colonist.", UtilityFunctions.AssemblyTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
				TextColonistName.Focus();
				return;
			}

			if (SpinColonistAge.Value < 10 || SpinColonistAge.Value > 100)
			{
				XtraMessageBox.Show("Saving failed! Please adjust the colonist age (10-100).", UtilityFunctions.AssemblyTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
				SpinColonistAge.Focus();
				return;
			}

			#endregion

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.Colonist({0}).{1}.rim", selectedPawn.ColonistName, DateTime.Now.ToOADate())));

			var xmlNodePawns = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");

			IEnumerator enumeratorPawns = null;

			try
			{
				if (xmlNodePawns != null)
				{

					enumeratorPawns = xmlNodePawns.GetEnumerator();

					while (enumeratorPawns != null && enumeratorPawns.MoveNext())
					{
						var currentPawn = (XmlElement)enumeratorPawns.Current;
						if (currentPawn.InnerXml.Contains(string.Concat("<ID>", selectedPawn.ColonistId, "</ID>")))
						{

							#region Basic

							// Name
							var elementsByTagName = currentPawn.GetElementsByTagName("CharacterName");
							elementsByTagName[0].InnerText = TextColonistName.Text;

							// Age
							elementsByTagName = currentPawn.GetElementsByTagName("Age");
							elementsByTagName[0].InnerText = SpinColonistAge.Value.ToString(CultureInfo.InvariantCulture);

							#endregion

							#region Backstory

							IEnumerator enumeratorBackstory = null;
							elementsByTagName = currentPawn.GetElementsByTagName("StoryItems");
							try
							{
								enumeratorBackstory = elementsByTagName.GetEnumerator();
								while (enumeratorBackstory != null && enumeratorBackstory.MoveNext())
								{
									var xmlElement = (XmlElement)enumeratorBackstory.Current;
									if (xmlElement.ParentNode != null && xmlElement.ParentNode.Name == "Story" && xmlElement.InnerXml.Contains("<Int32>"))
									{
										xmlElement.InnerXml = String.Format("<Int32>{0}</Int32>{1}\t\t\t\t\t<Int32>{2}</Int32>{1}",
											 LookUpColonistChildhood.EditValue,
											 Environment.NewLine,
											 LookUpColonistAdulthood.EditValue);
									}
								}
							}
							finally
							{
								if (enumeratorBackstory is IDisposable)
								{
									(enumeratorBackstory as IDisposable).Dispose();
								}
							}

							#endregion

							#region Traits

							IEnumerator enumeratorTraits = null;
							elementsByTagName = currentPawn.GetElementsByTagName("TraitList");
							try
							{
								enumeratorTraits = elementsByTagName.GetEnumerator();
								while (enumeratorTraits != null && enumeratorTraits.MoveNext())
								{
									var xmlElement = (XmlElement)enumeratorTraits.Current;
									if (xmlElement.ParentNode != null && Operators.CompareString(xmlElement.ParentNode.Name,
										 "Traits",
										 false) == 0)
									{
										var tempTraitText = String.Format("{0}\t\t\t\t\t<Trait Class=\"Trait\"> {0}\t\t\t\t\t\t<DefName>{{_trait1}}</DefName>{0}\t\t\t\t\t</Trait>{0}\t\t\t\t\t<Trait Class=\"Trait\"> {0}\t\t\t\t\t\t<DefName>{{_trait2}}</DefName>{0}\t\t\t\t\t</Trait>{0}",
											 Environment.NewLine);

										tempTraitText = tempTraitText.Replace("{_trait1}",
											 ComboColonistTrait1.EditValue.ToString());
										tempTraitText = tempTraitText.Replace("{_trait2}",
											 ComboColonistTrait2.EditValue.ToString());

										xmlElement.InnerXml = tempTraitText;
									}
								}
							}
							finally
							{
								if (enumeratorTraits is IDisposable)
								{
									(enumeratorTraits as IDisposable).Dispose();
								}
							}

							#endregion

							#region Skills
							IEnumerator enumeratorSkills = null;
							var elementsByTagSkill = currentPawn.GetElementsByTagName("Skills");

							try
							{
								enumeratorSkills = elementsByTagSkill.GetEnumerator();
								if (enumeratorSkills != null)
								{
									var childSkills = elementsByTagSkill[0];

									childSkills["Level_Construction"].InnerText = SpinColonistSkill_Construction.EditValue.ToString();
									childSkills["Level_Growing"].InnerText = SpinColonistSkill_Growing.EditValue.ToString();
									childSkills["Level_Research"].InnerText = SpinColonistSkill_Research.EditValue.ToString();
									childSkills["Level_Mining"].InnerText = SpinColonistSkill_Mining.EditValue.ToString();
									childSkills["Level_Shooting"].InnerText = SpinColonistSkill_Shooting.EditValue.ToString();
									childSkills["Level_Melee"].InnerText = SpinColonistSkill_Melee.EditValue.ToString();
									childSkills["Level_Social"].InnerText = SpinColonistSkill_Social.EditValue.ToString();
									childSkills["Level_Cooking"].InnerText = SpinColonistSkill_Cooking.EditValue.ToString();
									childSkills["Level_Medicine"].InnerText = SpinColonistSkill_Medicine.EditValue.ToString();
									childSkills["Level_Artistic"].InnerText = SpinColonistSkill_Artistic.EditValue.ToString();
									childSkills["Level_Crafting"].InnerText = SpinColonistSkill_Crafting.EditValue.ToString();
								}
							}
							finally
							{
								if (enumeratorSkills is IDisposable)
								{
									(enumeratorSkills as IDisposable).Dispose();
								}
							}

							#endregion

							#region Weapons

							IEnumerator enumeratorWeapons = null;
							elementsByTagName = currentPawn.GetElementsByTagName("Primary");
							try
							{
								enumeratorWeapons = elementsByTagName.GetEnumerator();
								while (enumeratorWeapons != null && enumeratorWeapons.MoveNext())
								{
									var xmlElement = (XmlElement)enumeratorWeapons.Current;
									if (xmlElement.ParentNode != null && xmlElement.ParentNode.Name == "Equipment")
									{
										if (LookUpColonistWeapon.EditValue == null)
										{
											var newAttr = xmlDocument.CreateAttribute("IsNull");
											newAttr.Value = "True";

											xmlElement.Attributes.Append(newAttr);

											xmlElement.InnerXml = String.Empty;
										}
										else
										{
											xmlElement.InnerXml = GenerateWeaponsSectionXml(LookUpColonistWeapon.EditValue);
										}
									}
								}
							}
							finally
							{
								if (enumeratorWeapons is IDisposable)
								{
									(enumeratorWeapons as IDisposable).Dispose();
								}
							}

							#endregion

						}
					}
				}
			}
			finally
			{
				if (enumeratorPawns is IDisposable)
				{
					(enumeratorPawns as IDisposable).Dispose();
				}
			}

			xmlDocument.Save(savefile);

			LoadColonists();

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} colonist is modified. Save modified.", selectedPawn.ColonistName);
		}

		private String GenerateWeaponsSectionXml(Object weaponIdO)
		{
			var weaponId = weaponIdO.ToString();
			var resultXmlInternal = weaponId + RandomHelper.Instance.Next(100000, 999999);

			var resultXmlFinal = String.Empty;

			resultXmlFinal += String.Format("\t\t\t\t\t<Def>{0}</Def>\r\n", weaponId);
			resultXmlFinal += String.Format("\t\t\t\t\t<ID>{0}</ID>\r\n", resultXmlInternal);
			resultXmlFinal += "\t\t\t\t\t<Health>100</Health>\r\n";

			return resultXmlFinal;
		}

		#endregion

		#region Form

		private void MainApplication_Load(object sender, EventArgs e)
		{
			LookUpColonistWeapon.Properties.DataSource = new WeaponList();
			LookUpColonistChildhood.Properties.DataSource = new BackstoryList(BackstoryTypes.Childhood);
			LookUpColonistAdulthood.Properties.DataSource = new BackstoryList(BackstoryTypes.Adulthood);
		}

		#region Custom tooltip

		private void LookUpGeneral_Properties_Popup(object sender, EventArgs e)
		{
			var popupControl = sender as IPopupControl;
			if (popupControl != null)
			{
				var popupWindow = popupControl.PopupWindow as PopupLookUpEditForm;

				if (popupWindow != null)
				{
					popupWindow.MouseMove += LookUpGeneral_PopupWindow_MouseMove;
					popupWindow.MouseLeave += LookUpGeneral_PopupWindow_MouseLeave;
				}
			}
		}

		private void LookUpGeneral_CloseUp(object sender, CloseUpEventArgs e)
		{
			var popupControl = sender as IPopupControl;
			if (popupControl != null)
			{
				var popupWindow = popupControl.PopupWindow as PopupLookUpEditForm;
				if (popupWindow != null)
				{
					popupWindow.MouseMove -= LookUpGeneral_PopupWindow_MouseMove;
					popupWindow.MouseLeave -= LookUpGeneral_PopupWindow_MouseLeave;
				}
			}
		}

		private void LookUpGeneral_PopupWindow_MouseMove(object sender, MouseEventArgs e)
		{
			var popupWindow = sender as PopupLookUpEditForm;

			if (popupWindow == null || popupWindow.SelectedIndex == -1)
			{
				return;
			}

			var targetLookUp = popupWindow.OwnerEdit;
			var dt = targetLookUp.Properties.DataSource as IThingList;

			if (dt != null)
			{
				var fetchedThing = dt.GetThingByIndex(popupWindow.SelectedIndex);

				if (fetchedThing != null)
				{
					DefaultToolTipControllerMain.DefaultController.ShowHint(fetchedThing.Tooltip.Replace(@"\n", String.Empty));
				}
			}
		}

		private void LookUpGeneral_PopupWindow_MouseLeave(object sender, EventArgs e)
		{
			DefaultToolTipControllerMain.DefaultController.HideHint();
		}

		#endregion

		#endregion

		#region File manager

		private void ButtonBrowse_Click(object sender, EventArgs e)
		{
			OpenSaveFileDialog.InitialDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"AppData\LocalLow\Ludeon Studios\RimWorld\");

			if (OpenSaveFileDialog.ShowDialog(this) == DialogResult.OK)
			{
				Settings.Default.SelectedSaveFilePath = OpenSaveFileDialog.FileName;
				var directoryInfo = new FileInfo(OpenSaveFileDialog.FileName).Directory;
				if (directoryInfo != null)
					Settings.Default.BackupSaveFilePath = directoryInfo.FullName + @"\Backups\";

				TextSavePath.Text = OpenSaveFileDialog.FileName;

				var savefile = Settings.Default.SelectedSaveFilePath;

				var xmlDocument = new XmlDocument();
				xmlDocument.Load(savefile);

				var selectSingleNode = xmlDocument.SelectSingleNode("/Map/GameVersion");
				if (selectSingleNode != null)
				{
					TextGameVersion.Text = selectSingleNode.InnerText;
				}

				selectSingleNode = xmlDocument.SelectSingleNode("/Map/ColonyInfo/ColonyName");
				if (selectSingleNode != null)
				{
					TextColonyName.Text = selectSingleNode.InnerText;
				}

			}
		}

		private void ButtonLoad_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			LoadResources();
			LoadColonists();

			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status_Loaded_Success;
		}

		#endregion

		#region Resource manager

		private void ButtonSaveResources_Click(object sender, EventArgs e)
		{
			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.Resources.{0}.rim", DateTime.Now.ToOADate())));

			var selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Money");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinMoney.Value.ToString(CultureInfo.InvariantCulture);
			}

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Food");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinFood.Value.ToString(CultureInfo.InvariantCulture);
			}

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Metal");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinMetal.Value.ToString(CultureInfo.InvariantCulture);
			}

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Medicine");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinMedicine.Value.ToString(CultureInfo.InvariantCulture);
			}

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Shells");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinShells.Value.ToString(CultureInfo.InvariantCulture);
			}

			selectSingleNode = xmlDocument.SelectSingleNode("/Map/Resources/Missiles");
			if (selectSingleNode != null)
			{
				selectSingleNode.InnerText = SpinMissiles.Value.ToString(CultureInfo.InvariantCulture);
			}

			// Save
			xmlDocument.Save(savefile);
		}

		private void SpinGeneric_ButtonClick(object sender, ButtonPressedEventArgs e)
		{
			var senderButton = sender as SpinEdit;
			var conditionReload = e.Button.Kind == ButtonPredefines.Undo;

			if (conditionReload)
			{
				if (senderButton != null)
				{
					ReloadResource((ResourceTypesOld)senderButton.Tag);
				}
			}
		}

		#endregion

		#region Cleanup manager

		private void ButtonCorpse_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.CorpseRemove.{0}.rim", DateTime.Now.ToOADate())));

			IEnumerator enumerator = null;
			int counterModifications;

			try
			{
				counterModifications = 0;
				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Corpse']");
				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlNode)enumerator.Current;
						if (current.InnerXml.Contains("<Def>Corpse</Def>"))
						{
							if (current.ParentNode != null)
							{
								current.ParentNode.RemoveChild(current);
								counterModifications++;
							}
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			xmlDocument.Save(savefile);
			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} corpse removed. Save modified.", counterModifications);
		}

		private void ButtonFixWalls_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.WallRepair.{0}.rim", DateTime.Now.ToOADate())));
			IEnumerator enumerator = null;
			int counterModifications;

			try
			{
				counterModifications = 0;

				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Building']");

				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();

					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlNode)enumerator.Current;
						if (current.InnerXml.Contains("<Def>Wall</Def>"))
						{
							XmlNode item = current["Health"];

							if (item != null)
							{
								item.InnerText = 280.ToString(CultureInfo.InvariantCulture);
								counterModifications++;
							}
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			// Save
			xmlDocument.Save(savefile);

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} walls repaired. Save modified.", counterModifications);
		}

		private void ButtonCleanup_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.Cleanup.{0}.rim", DateTime.Now.ToOADate())));
			IEnumerator enumerator = null;
			int counterModifications;

			try
			{
				counterModifications = 0;

				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Filth']");
				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlNode)enumerator.Current;
						if (current.ParentNode != null)
						{
							current.ParentNode.RemoveChild(current);
							counterModifications++;
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			// Save
			xmlDocument.Save(savefile);

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} filth cleaned. Save modified.", counterModifications);
		}

		#endregion

		#region Raiders manager

		private void ButtonWeakenRaidersBy_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.RaiderWeaken.{0}.rim", DateTime.Now.ToOADate())));
			IEnumerator enumerator = null;
			int counterModifications;

			var targetHealth = Conversions.ToInteger(SpinWeakenRaidersBy.Value);

			try
			{
				counterModifications = 0;

				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");
				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlNode)enumerator.Current;
						if (current.InnerXml.Contains("<Team>Raider</Team>") && current.InnerXml.Contains("<HealthTracker>"))
						{
							var xmlElement = current["HealthTracker"];
							if (xmlElement != null)
							{
								xmlElement.InnerText = Conversions.ToString(0);
								counterModifications++;
							}
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			xmlDocument.Save(savefile);

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} raiders have {1} health point(s) now. Save modified.", counterModifications, targetHealth);
		}

		private void ButtonRemoveRaiders_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.RaiderRemove.{0}.rim", DateTime.Now.ToOADate())));
			IEnumerator enumerator = null;
			int counterModifications;

			try
			{
				counterModifications = 0;
				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");
				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlNode)enumerator.Current;
						if (current.InnerXml.Contains("<Team>Raider</Team>") && current.InnerXml.Contains("<HealthTracker>"))
						{
							if (current.ParentNode != null)
							{
								current.ParentNode.RemoveChild(current);
								counterModifications++;
							}
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			xmlDocument.Save(savefile);
			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} raiders have just vanished. Save modified.", counterModifications);
		}

		#endregion

		#region Colonist manager

		private void ButtonHealColonists_Click(object sender, EventArgs e)
		{
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);
			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.ColonistHeal.{0}.rim", DateTime.Now.ToOADate())));
			IEnumerator enumerator = null;
			int counterModifications;

			try
			{
				counterModifications = 0;
				var xmlNodeList = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");
				if (xmlNodeList != null)
				{
					enumerator = xmlNodeList.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var currentPawn = (XmlNode)enumerator.Current;
						if (currentPawn.InnerXml.Contains("<Team>Colonist</Team>") && currentPawn.InnerXml.Contains("<Kind>Colonist</Kind>"))
						{
							var extraHealth = false;

							// See if the tough trait is avaliable.
							XmlNode item = currentPawn["Traits"];
							if (item != null && item.InnerXml.Contains("<DefName>Tough</DefName>"))
							{
								// It does so flag for extra 50 HP
								extraHealth = true;
							}

							item = currentPawn["HealthTracker"];
							if (item != null)
							{
								var xmlElement = item["PawnHealth"];
								if (xmlElement != null)
								{
									xmlElement.InnerText = Conversions.ToString(extraHealth ? 150 : 100);
									counterModifications++;
								}
							}

							// Rested
							item = currentPawn["Rest"];
							if (item != null)
							{
								var xmlElement = item["PieceRest"];
								if (xmlElement != null)
								{
									var xmlElement1 = xmlElement["CurLevel"];
									if (xmlElement1 != null)
									{
										xmlElement1.InnerText = Conversions.ToString(100);
									}
								}
							}
							// Feed
							item = currentPawn["Food"];
							if (item != null)
							{
								var xmlElement = item["PieceFood"];
								if (xmlElement != null)
								{
									var xmlElement1 = xmlElement["CurLevel"];
									if (xmlElement1 != null)
									{
										xmlElement1.InnerText = Conversions.ToString(100);
									}
								}
							}
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
			}

			xmlDocument.Save(savefile);

			LoadColonists();

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} colonist are rested, well-fed, and have full HP now. Save modified.", counterModifications);
		}

		private void ListColonist_SelectedIndexChanged(object sender, EventArgs e)
		{
			Cursor.Current = Cursors.WaitCursor;
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			// Reset
			TextColonistID.Text = String.Empty;
			TextColonistName.Text = String.Empty;
			TextColonistSex.Text = String.Empty;
			SpinColonistAge.Value = 10;
			LookUpColonistChildhood.EditValue = null;
			LookUpColonistAdulthood.EditValue = null;
			ComboColonistTrait1.SelectedIndex = -1;
			ComboColonistTrait2.SelectedIndex = -1;
			LookUpColonistWeapon.EditValue = null;
			SpinColonistSkill_Construction.EditValue = 0;
			SpinColonistSkill_Growing.EditValue = 0;
			SpinColonistSkill_Research.EditValue = 0;
			SpinColonistSkill_Mining.EditValue = 0;
			SpinColonistSkill_Shooting.EditValue = 0;
			SpinColonistSkill_Melee.EditValue = 0;
			SpinColonistSkill_Social.EditValue = 0;
			SpinColonistSkill_Cooking.EditValue = 0;
			SpinColonistSkill_Medicine.EditValue = 0;
			SpinColonistSkill_Artistic.EditValue = 0;
			SpinColonistSkill_Crafting.EditValue = 0;
			SpinColonistSkill_All.EditValue = 0;

			if (!CheckFileExistance())
			{
				return;
			}

			if (ListColonist.SelectedItems.Count <= 0)
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);

			IEnumerator enumerator = null;
			IEnumerator enumeratorTraits = null;
			IEnumerator enumeratorStories = null;
			IEnumerator enumeratorSkills = null;

			var selectedPawn = ListColonist.SelectedItem as PawnListItem;

			var xmlNodeLists = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");

			try
			{
				if (xmlNodeLists != null && selectedPawn != null)
				{
					enumerator = xmlNodeLists.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						var current = (XmlElement)enumerator.Current;
						if (current.InnerXml.Contains(String.Concat("<ID>", selectedPawn.ColonistId, "</ID>")))
						{

							#region Basic info

							TextColonistID.Text = selectedPawn.ColonistId;
							TextColonistName.Text = selectedPawn.ColonistName;

							var elementsByTagTemp = current.GetElementsByTagName("Sex");
							if (elementsByTagTemp.Count > 0)
							{
								TextColonistSex.Text = elementsByTagTemp[0].InnerText;
							}

							elementsByTagTemp = current.GetElementsByTagName("Age");
							if (elementsByTagTemp.Count > 0)
							{
								SpinColonistAge.Value = Int32.Parse(elementsByTagTemp[0].InnerText);
							}

							#endregion

							#region Backstory

							var elementsByBackstory = current.GetElementsByTagName("StoryItems");

							try
							{
								enumeratorStories = elementsByBackstory.GetEnumerator();

								if (enumeratorStories != null)
								{
									var childStories = elementsByBackstory[0];

									var childDb = LookUpColonistChildhood.Properties.DataSource as IThingList;

									if (childDb != null)
										LookUpColonistChildhood.EditValue = ((BackstoryListItem)childDb.GetThingById(childStories.ChildNodes[0].InnerText)).StoryId;

									var adultDb = LookUpColonistAdulthood.Properties.DataSource as IThingList;

									if (adultDb != null)
										LookUpColonistAdulthood.EditValue = ((BackstoryListItem)adultDb.GetThingById(childStories.ChildNodes[1].InnerText)).StoryId;
								}
							}
							finally
							{
								if (enumeratorStories is IDisposable)
								{
									(enumeratorStories as IDisposable).Dispose();
								}
							}

							#endregion

							#region Traits

							var elementsByTagTrait = current.GetElementsByTagName("TraitList");

							try
							{
								enumeratorTraits = elementsByTagTrait.GetEnumerator();
								if (enumeratorTraits != null)
								{
									var childTraits = elementsByTagTrait[0];

									ComboColonistTrait1.EditValue = childTraits.ChildNodes[0].InnerText;
									ComboColonistTrait2.EditValue = childTraits.ChildNodes[1].InnerText;
								}
							}
							finally
							{
								if (enumeratorTraits is IDisposable)
								{
									(enumeratorTraits as IDisposable).Dispose();
								}
							}

							#endregion

							#region Skills
							var elementsByTagSkill = current.GetElementsByTagName("Skills");

							try
							{
								enumeratorSkills = elementsByTagSkill.GetEnumerator();
								if (enumeratorSkills != null)
								{
									var childSkills = elementsByTagSkill[0];

									SpinColonistSkill_Construction.EditValue = childSkills["Level_Construction"].InnerText;
									SpinColonistSkill_Growing.EditValue = childSkills["Level_Growing"].InnerText;
									SpinColonistSkill_Research.EditValue = childSkills["Level_Research"].InnerText;
									SpinColonistSkill_Mining.EditValue = childSkills["Level_Mining"].InnerText;
									SpinColonistSkill_Shooting.EditValue = childSkills["Level_Shooting"].InnerText;
									SpinColonistSkill_Melee.EditValue = childSkills["Level_Melee"].InnerText;
									SpinColonistSkill_Social.EditValue = childSkills["Level_Social"].InnerText;
									SpinColonistSkill_Cooking.EditValue = childSkills["Level_Cooking"].InnerText;
									SpinColonistSkill_Medicine.EditValue = childSkills["Level_Medicine"].InnerText;
									SpinColonistSkill_Artistic.EditValue = childSkills["Level_Artistic"].InnerText;
									SpinColonistSkill_Crafting.EditValue = childSkills["Level_Crafting"].InnerText;

								}
							}
							finally
							{
								if (enumeratorSkills is IDisposable)
								{
									(enumeratorSkills as IDisposable).Dispose();
								}
							}
							#endregion

							#region Weapon

							var elementsByTagName = current.GetElementsByTagName("Primary");
							var enumeratorWeapons = elementsByTagName.GetEnumerator();

							try
							{
								while (enumeratorWeapons != null && enumeratorWeapons.MoveNext())
								{
									var xmlElement = (XmlElement)enumeratorWeapons.Current;
									if (xmlElement.ParentNode != null && (Operators.CompareString(xmlElement.ParentNode.Name,
										 "Equipment",
										 false) == 0 && xmlElement.InnerXml.Contains("<Def>")))
									{
										var element = xmlElement["Def"];
										if (element != null)
										{
											LookUpColonistWeapon.EditValue = element.InnerText;
										}
									}
								}
							}
							finally
							{
								if (enumeratorWeapons is IDisposable)
								{
									(enumeratorWeapons as IDisposable).Dispose();
								}
							}

							#endregion

						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
				Cursor.Current = Cursors.Default;
			}

			if (selectedPawn != null)
			{
				BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} have been loaded.", selectedPawn.ColonistName);
			}
		}

		private void ButtonSaveColonist_Click(object sender, EventArgs e)
		{
			UpdateColonist();
		}

		private void SpinColonistSkill_All_EditValueChanged(object sender, EventArgs e)
		{
			SpinColonistSkill_Construction.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Growing.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Research.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Mining.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Shooting.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Melee.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Social.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Cooking.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Medicine.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Artistic.EditValue = SpinColonistSkill_All.EditValue;
			SpinColonistSkill_Crafting.EditValue = SpinColonistSkill_All.EditValue;
		}

		private void ButtonClone_Click(object sender, EventArgs e)
		{
			Cursor.Current = Cursors.WaitCursor;
			BarManagerMain_StatusBar_StaticItemReport.Caption = Resources.Basic_String_Status;

			if (!CheckFileExistance())
			{
				return;
			}

			var selectedPawn = ListColonist.SelectedItem as PawnListItem;

			if (selectedPawn == null)
			{
				return;
			}

			var savefile = Settings.Default.SelectedSaveFilePath;

			var xmlDocument = new XmlDocument();
			xmlDocument.Load(savefile);

			SaveFile(ref xmlDocument, savefile.Replace(".rim", String.Format(".before.Colonist({0}) cloning.{1}.rim", selectedPawn.ColonistName, DateTime.Now.ToOADate())));

			IEnumerator enumerator = null;

			var xmlNodeLists = xmlDocument.SelectNodes("/Map/Things/Thing[@Class='Pawn']");

			try
			{
				if (xmlNodeLists != null)
				{
					XmlNode clonedPawn = null;
					var pawnIDs = new List<String>();

					XmlElement current = null;
					enumerator = xmlNodeLists.GetEnumerator();
					while (enumerator != null && enumerator.MoveNext())
					{
						current = (XmlElement)enumerator.Current;

						var elementsByTagTemp = current.GetElementsByTagName("ID");
						if (elementsByTagTemp.Count > 0)
						{
							pawnIDs.Add(elementsByTagTemp[0].InnerText.Replace("Pawn", String.Empty));
						}

						if (current.InnerXml.Contains(String.Concat("<ID>", selectedPawn.ColonistId, "</ID>")))
						{
							clonedPawn = current.CloneNode(true);
						}
					}

					// Generate new name
					var xmlElement = (XmlElement)clonedPawn;
					if (xmlElement != null)
					{
						var elementsByTagNewNameTemp = xmlElement.GetElementsByTagName("CharacterName");
						if (elementsByTagNewNameTemp.Count > 0)
						{
							elementsByTagNewNameTemp[0].InnerText = elementsByTagNewNameTemp[0].InnerText + "Cloned";
						}
					}

					// Detach bed
					xmlElement = (XmlElement)clonedPawn;
					if (xmlElement != null)
					{
						var elementsByTagNewNameTemp = xmlElement.GetElementsByTagName("OwnedBed");
						if (elementsByTagNewNameTemp.Count > 0)
						{
							elementsByTagNewNameTemp[0].InnerText = String.Empty;
						}
					}

					// Randimize ID of anything with tagname of ID
					var newPawnId = RandomHelper.Instance.Next(1, 9999999).ToString(CultureInfo.InvariantCulture);
					var element = (XmlElement)clonedPawn;
					if (element != null)
					{
						var elementsByTagNewIdTemp = element.GetElementsByTagName("ID");
						if (elementsByTagNewIdTemp.Count > 0)
						{
							var enumeratorId = elementsByTagNewIdTemp.GetEnumerator();
							while (enumeratorId != null && enumeratorId.MoveNext())
							{
								while (pawnIDs.Contains(newPawnId))
								{
									newPawnId = RandomHelper.Instance.Next(1, 9999999).ToString(CultureInfo.InvariantCulture);
								}

								var reversed = elementsByTagNewIdTemp[0].InnerText.ToCharArray();
								Array.Reverse(reversed);

								var i = 0;
								var reversedId = String.Empty;

								while (Char.IsDigit(reversed[i]))
								{
									reversedId = reversedId + reversed[i];
									i++;
								}

								var idBackInOrder = reversedId.ToCharArray();
								Array.Reverse(idBackInOrder);

								var numericOnlyId = new String(idBackInOrder);

								elementsByTagNewIdTemp[0].InnerText = elementsByTagNewIdTemp[0].InnerText.Replace(numericOnlyId, String.Empty) + newPawnId;

							}

							if (current.ParentNode != null)
								current.ParentNode.AppendChild(clonedPawn);
						}
					}
				}
			}
			finally
			{
				if (enumerator is IDisposable)
				{
					(enumerator as IDisposable).Dispose();
				}
				Cursor.Current = Cursors.Default;
			}

			xmlDocument.Save(savefile);

			LoadColonists();

			BarManagerMain_StatusBar_StaticItemReport.Caption = String.Format("Status: {0} have been cloned.", selectedPawn.ColonistName);
		}

		#endregion

		private void BarManagerMain_StatusBar_ButtonPaypal_ItemClick(object sender, ItemClickEventArgs e)
		{
			var url = "";

			const string business = "hassan.gulzar@gmail.com";
			var description = String.Format("Donate{0}something{1}{0}Not{0}that{0}it{0}is{0}required{0}but{0}if{0}you{0}don{2}t{0}mind{3}{0}then{0}I{0}definitely{0}don{2}t{0}either{4}", "%20", "%2E", "%B4", "%2C", "%21");
			const string country = "US";
			const string currency = "USD";

			url += "https://www.paypal.com/cgi-bin/webscr" + "?cmd=" + "_donations" + "&business=" + business + "&lc=" + country + "&item_name=" + description + "&currency_code=" + currency + "&bn=" + "PP%2dDonationsBF";

			Process.Start(url);
		}

		private void BarManagerMain_StatusBar_ButtonAbout_ItemClick(object sender, ItemClickEventArgs e)
		{
			new AboutApp().ShowDialog(this);
		}

		private void LookUpColonistWeapon_Properties_ButtonClick(object sender, ButtonPressedEventArgs e)
		{
			if (e.Button.Kind == ButtonPredefines.Delete)
			{
				LookUpColonistWeapon.EditValue = null;
			}
		}

	}
}